/***************************************************************************

Copyright (c) BizRulX. All rights reserved.

***************************************************************************/

using System;
using System.Globalization;
using Microsoft.VisualStudio.Shell;

namespace RuleXSoft.BizRuleCreator
{
	/// <summary>
	/// This attribute adds a logical view to the editor created by an editor factory.
	/// </summary>
	[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
    [System.Runtime.InteropServices.ComVisibleAttribute(false)]
	public sealed class XmlDesignerViewAttribute : RegistrationAttribute
	{
        #region Fields
        private Guid factory;
        private Guid logicalView;
        private string name;
        private string extension;
        private string xmlNamespace;
        private bool matchboth;
        #endregion

        #region Constructors
        /// <summary>
        /// Creates a new RegisterEditorLogicalView attribute to register a logical
        /// view provided by your editor.
        /// </summary>
        /// <param name="factoryType">The type of factory; can be a Type, a GUID or a string representation of a GUID</param>
        /// <param name="logicalViewGuid">The guid of the logical view to register.</param>
        public XmlDesignerViewAttribute(object factoryType, string logicalViewGuid)
        {
            if (factoryType == null)
            {
                throw new ArgumentNullException(Resources.ParameterNameFactoryType, Resources.ExceptionMessageNullFactoryType);
            }

            this.logicalView = new Guid(logicalViewGuid);

            // figure out what type of object they passed in and get the GUID from it
            // check stringType for String type
            string stringType = factoryType as string;
            if (stringType != null)
            {
                this.factory = new Guid(stringType);
            }
            else
            {
                Type typeType = factoryType as Type;
                if (typeType != null)
                {
                    this.factory = typeType.GUID;
                    this.name = (this.name == null) ? typeType.Name : this.name;
                }
                else if (factoryType is Guid)
                {
                    this.factory = (Guid)factoryType;
                }
                else
                {
                    // factoryType is of unaccaptable type
                    throw new ArgumentException(Resources.ArgumentExceptionMessageParameter, Resources.ParameterNameFactoryType);
                }
            }
        }
        #endregion

        #region Properties
        /// <summary>
        /// Gets the object (Guid) that represent the type of representing the type of the editor factory
        /// </summary>
        public object FactoryType
        {
            get { return factory; }
        }

        /// <summary>
        /// Implements readonly accessor for positional argument 'factoryType' 
        /// </summary>
        public string LogicalViewGuid
        {
            get { return logicalView.ToString(); }
        }
    
        /// <summary>
        /// Get the Guid representing the logical view
        /// </summary>
        public Guid LogicalView
        {
            get { return logicalView; }
        }

        /// <summary>
        /// Get or Set the name of the editor
        /// </summary>
        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        /// <summary>
        /// Get or Set the namespace of the XML files that support this view
        /// </summary>
        public string XmlNamespace
        {
            get { return xmlNamespace; }
            set { xmlNamespace = value; }
        }

        /// <summary>
        /// Get or Set the extension of the XML files that support this view
        /// </summary>
        public string Extension
        {
            get { return extension; }
            set { extension = value; }
        }

        /// <summary>
        /// Get or Set the whether the XML files that support this view must
        /// match both the file extension and the namespace (Match = "both")
        /// or it is OK to merely match the file extension (Match not specified)
        /// </summary>
        public bool MatchBoth
        {
            get { return matchboth; }
            set { matchboth = value; }
        }

        /// <summary>
        /// XmlView path within the registration context
        /// </summary>
        private string XmlViewPath
        {
            get { return string.Format(CultureInfo.InvariantCulture, "XmlDesigners\\{0}", factory.ToString("B")); }
        }
        #endregion

        #region Methods
        /// <summary>
        /// Called to register this attribute with the given context.  The context
        /// contains the location where the registration inforomation should be placed.
        /// It also contains other information such as the type being registered and path information.
        /// </summary>
        /// <param name="context">Given context to register in</param>
        public override void Register(RegistrationContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            context.Log.WriteLine(String.Format(CultureInfo.CurrentCulture, "XmlDesignerView:  {0}\n", name));

            using (Key childKey = context.CreateKey(XmlViewPath))
            {
                childKey.SetValue("Editor", factory.ToString("D"));
                childKey.SetValue("LogicalView", logicalView.ToString("D"));

                if (name == null)
                {
                    name = string.Empty;
                }
                childKey.SetValue(null, name);

                if (xmlNamespace != null)
                {
                    childKey.SetValue("Namespace", xmlNamespace);
                }

                if (extension != null)
                {
                    childKey.SetValue("Extension", extension);
                }

                if (matchboth)
                {
                    childKey.SetValue("Match", "both");
                }
            }
        }

        /// <summary>
        /// Unregister this logical view.
        /// </summary>
        /// <param name="context"></param>
        public override void Unregister(RegistrationContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            context.RemoveKey(XmlViewPath);
        }
        #endregion
    }
}
